package affichagePlateau;


import java.util.Scanner;

import plateau.PlateauInfini;

import structureDeDonnee.Cell;
import structureDeDonnee.Matrice;
import structureDeDonnee.Position;

/**
 * Classe fournissant une méthode permettant l'affichage des plateaux infinis
 * 
 */
public class AffichagePlateauInfini {

	public static Scanner sc = new Scanner(System.in);

	/**
	 * Methode produisant l'affichage, cette methode (à l'aide d'autres méthodes
	 * présentes dans la clase) permettra de se déplacer sur le plateau
	 * d'arrêter le programme et de passer a la génération suivant
	 * 
	 * @param p
	 *            le plateau que l'on doit afficher
	 * @return un boolean permettant de savoir si l'utilisateur veut passer à la
	 *         génération suivante (oui=true, false= non)
	 */
	public static boolean display(PlateauInfini p) {
		Matrice listCells = p.getMatrice();
		if (!listCells.isEmpty()) {
			Position firstCellsPosition = listCells.getPremiereCellule()
					.getPosition();
			System.out.println("NBCELLULES : " + listCells.length());
			int posX = firstCellsPosition.getX();
			int posY = firstCellsPosition.getY();
			displayOfTheGame(posX, posY, listCells);
			while (continueDisplay()) {
				posX = askNewNumber('x');
				posY = askNewNumber('y');
				displayOfTheGame(posX, posY, listCells);
			}
			System.out.println("Passer a la génération suivante?(O/n)");
			while (true) {
				String input = sc.next();
				if (input.equals("o") || input.equals("O")) {
					return true;
				} else if (input.equals("n") || input.equals("N")) {
					return false;
				}
			}
		} else {
			System.out.println("Fini : Jeu mort");
			return false;
		}
	}

	/**
	 * Méthode produisant l'affichage à l'aide de boucles for
	 * 
	 * @param posX
	 *            la position en abcisse de référence (position en haut à
	 *            gauche)
	 * @param posY
	 *            la position en ordonnée de référence (position en haut à
	 *            gauche)
	 * @param listCells
	 *            la liste de cellules nous permettant de savoir si il y a une
	 *            cellule à une coordonnées données
	 */
	private static void displayOfTheGame(int posX, int posY,
			Matrice listCells) {
		System.out.println("posx : "+posX+" posY : "+posY);
		for (int i = posY; i > posY - 80; --i) {
			for (int j = posX; j < posX + 80; ++j) {
				if (listCells.contains(new Cell(j, i))) {
					System.out.print("*");
				} else {
					System.out.print(" ");
				}
			}
			System.out.println();
		}
	}

	/**
	 * Méthode qui demande à l'utilisateur si il veut continuer ou pas à se
	 * déplacer sur le plateau et gérant les input invalides
	 * 
	 * @return un booléen permettant de savoir si l'on veut continuer ou pas à
	 *         se déplacer sur le plateau
	 */
	private static boolean continueDisplay() {
		System.out
				.println("Voulez vous changer de coordonnées de référence?(O/n)");
		String choice = sc.next();
		if (choiceIsGood(choice)) {
			if (choice.equals("o") || choice.equals("O")) {
				return true;
			} else {
				return false;
			}
		} else {
			return continueDisplay();
		}
	}

	/**
	 * méthode gérant la validité de l'input
	 * 
	 * @param choice
	 *            la String que l'user à rentrée
	 * @return un boolean pour savoir si le choix est conforme ou pas
	 */
	private static boolean choiceIsGood(String choice) {
		if (choice.equals("o") || choice.equals("O") || choice.equals("n")
				|| choice.equals("N")) {
			return true;
		}
		return false;
	}

	/**
	 * Méthode demandant la nouvelle coordonnée de référence
	 * 
	 * @param letter
	 *            permet juste au programme d'afficher un message avec letter
	 *            (on passera y à cette méthode lorsque l'on veut demander les
	 *            coordonnées en ordonnée)
	 * @return la nouvelle valeur
	 */
	private static int askNewNumber(char letter) {
		int numberToReturn = 0;
		boolean retour = false;
		while (!retour) {
			System.out.println("Donnez la nouvelle position en " + letter);
			try {
				numberToReturn = Integer.parseInt(sc.next());
				retour = true;
			} catch (NumberFormatException e) {
				System.out
						.println("Input invalide : veuillez donnez un nombre");
			}
		}
		return numberToReturn;
	}

}
